using Microsoft.EntityFrameworkCore;
using RAG.Application.Interfaces;
using RAG.Application.Dtos;
using RAG.Domain.Entities.App;
using RAG.Infrastructure.Data;
using System.Text;
using System.Text.Json;
using Microsoft.Extensions.Configuration;
using RAG.Application.Commands; // This using statement is crucial for ApiResult
using System.Security.Cryptography;
using System.Web;
using RAG.Application.Services; // For PermissionCheckService

namespace RAG.Application.Services;

/// <summary>
/// RAG服务实现
/// </summary>
public class AppRagService : IAppRagService
{
    private readonly RagDbContext _db;
    private readonly IConfiguration _configuration;
    private readonly IVectorService _vectorService;
    private readonly IDocumentProcessingService _documentProcessingService;
    private readonly PermissionCheckService _permissionCheckService;

    public AppRagService(RagDbContext db, IConfiguration configuration, IVectorService vectorService, PermissionCheckService permissionCheckService, IDocumentProcessingService documentProcessingService)
    {
        _db = db;
        _configuration = configuration;
        _vectorService = vectorService;
        _permissionCheckService = permissionCheckService;
        _documentProcessingService = documentProcessingService;
    }

    /// <summary>
    /// 处理文档并生成向量
    /// </summary>
    public async Task<ApiResult> ProcessDocumentAsync(Guid documentId)
    {
        try
        {
            var document = await _db.Documents
                .Include(d => d.DocumentChunks)
                .FirstOrDefaultAsync(d => d.DocumentId == documentId);

            if (document == null)
            {
                return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "文档不存在");
            }

            // 更新文档状态为处理中
            document.DocumentStatus = "processing";
            await _db.SaveChangesAsync();

            try
            {
                // 读取文档内容（使用文档处理服务，支持多种格式例如 .docx/.md/.txt 等）
                var fullPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", document.DocumentFilePath);
                if (!File.Exists(fullPath))
                {
                    document.DocumentStatus = "error";
                    await _db.SaveChangesAsync();
                    return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "文档文件不存在");
                }

                var content = await _documentProcessingService.ExtractTextAsync(fullPath, document.DocumentFileType);
                
                // 分块处理
                var chunks = await _documentProcessingService.SplitIntoChunksAsync(content, 1000); // 每块1000字符
                
                // 删除现有的文档块和向量
                var existingChunks = await _db.DocumentChunks
                    .Where(dc => dc.DocumentId == documentId)
                    .ToListAsync();
                
                var existingChunkIds = existingChunks.Select(c => c.Id).ToList();
                var existingVectors = await _db.Vectors
                    .Where(v => existingChunkIds.Contains(v.DocumentChunkId))
                    .ToListAsync();
                
                _db.Vectors.RemoveRange(existingVectors);
                _db.DocumentChunks.RemoveRange(existingChunks);
                await _db.SaveChangesAsync();

                // 创建新的文档块
                var documentChunks = new List<DocumentChunk>();
                for (int i = 0; i < chunks.Count; i++)
                {
                    var chunk = new DocumentChunk
                    {
                        Id = Guid.NewGuid(),
                        DocumentId = documentId,
                        ChunkIndex = i,
                        DocumentChunkContent = chunks[i],
                        TokenCount = chunks[i].Length, // 简单估算token数量
                        CreatedAt = DateTime.UtcNow,
                        UpdatedAt = DateTime.UtcNow
                    };

                    documentChunks.Add(chunk);
                }

                // 批量插入文档块
                _db.DocumentChunks.AddRange(documentChunks);
                await _db.SaveChangesAsync();

                // 为每个文档块生成向量并保存
                var vectors = new List<Vector>();
                for (int i = 0; i < documentChunks.Count; i++)
                {
                    var chunk = documentChunks[i];
                    var embedding = await _vectorService.GenerateEmbeddingAsync(chunk.DocumentChunkContent);
                    
                    var vector = new Vector
                    {
                        VectorId = Guid.NewGuid(),
                        DocumentChunkId = chunk.Id,
                        Embedding = embedding,
                        CreatedAt = DateTime.UtcNow,
                        UpdatedAt = DateTime.UtcNow
                    };
                    
                    vectors.Add(vector);
                }

                // 批量插入向量
                _db.Vectors.AddRange(vectors);
                await _db.SaveChangesAsync();

                // 更新文档状态为已完成
                document.DocumentStatus = "completed";
                document.UpdatedAt = DateTime.UtcNow;
                await _db.SaveChangesAsync();

                return ApiResult.Success("文档处理完成", new { 
                    chunkCount = chunks.Count,
                    vectorCount = vectors.Count,
                    documentId = documentId
                });
            }
            catch (Exception ex)
            {
                document.DocumentStatus = "error";
                await _db.SaveChangesAsync();
                return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"文档处理失败: {ex.Message}");
            }
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"处理文档失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 检索相关文档块
    /// </summary>
    public async Task<ApiResult> RetrieveRelevantChunksAsync(string query, Guid? knowledgeBaseId = null, int topK = 5)
    {
        try
        {
            var queryBuilder = _db.DocumentChunks
                .Include(dc => dc.Document)
                .ThenInclude(d => d.KnowledgeBase)
                .AsQueryable();

            if (knowledgeBaseId.HasValue)
            {
                queryBuilder = queryBuilder.Where(dc => dc.Document.KnowledgeBaseId == knowledgeBaseId.Value);
            }

            // 获取所有候选文档块
            var candidateChunks = await queryBuilder
                .Select(dc => new
                {
                    dc.Id,
                    dc.ChunkIndex,
                    dc.DocumentChunkContent,
                    dc.TokenCount,
                    DocumentTitle = dc.Document.DocumentTitle,
                    KnowledgeBaseName = dc.Document.KnowledgeBase.KnowledgeBaseName
                })
                .ToListAsync();

            if (!candidateChunks.Any())
            {
                return ApiResult.Success("未找到相关文档块", new List<object>());
            }

            // 生成查询向量
            var queryVector = await _vectorService.GenerateEmbeddingAsync(query);

            // 获取所有候选向量的向量数据
            var vectorData = new List<VectorData>();
            foreach (var chunk in candidateChunks)
            {
                var embedding = await _vectorService.GetVectorAsync(chunk.Id);
                if (embedding != null)
                {
                    vectorData.Add(new VectorData
                    {
                        ChunkId = chunk.Id,
                        Vector = embedding,
                        Content = chunk.DocumentChunkContent
                    });
                }
            }

            // 执行向量相似度搜索
            var searchResults = await _vectorService.SearchSimilarVectorsAsync(queryVector, vectorData, topK);

            // 构建返回结果
            var relevantChunks = searchResults.Select(result => new
            {
                Id = result.ChunkId,
                ChunkIndex = candidateChunks.First(c => c.Id == result.ChunkId).ChunkIndex,
                DocumentChunkContent = result.Content,
                TokenCount = candidateChunks.First(c => c.Id == result.ChunkId).TokenCount,
                DocumentTitle = candidateChunks.First(c => c.Id == result.ChunkId).DocumentTitle,
                KnowledgeBaseName = candidateChunks.First(c => c.Id == result.ChunkId).KnowledgeBaseName,
                Similarity = result.Similarity
            }).ToList();

            return ApiResult.Success("检索完成", relevantChunks);
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"检索文档块失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 从所有知识库中检索相关文档块
    /// </summary>
    public async Task<ApiResult> RetrieveRelevantChunksFromAllKnowledgeBasesAsync(string query, Guid userId, int topK = 5)
    {
        try
        {
            // 获取所有活跃的知识库（所有用户都可以访问所有知识库）
            var allKnowledgeBases = await _db.KnowledgeBases
                .Where(kb => kb.IsActive && !kb.IsDeleted)
                .ToListAsync();
            
            if (!allKnowledgeBases.Any())
            {
                Console.WriteLine("系统中没有可用的知识库");
                return ApiResult.Success("没有可用的知识库", new List<object>());
            }

            Console.WriteLine($"系统中共有 {allKnowledgeBases.Count} 个知识库，所有用户都可以访问");

            // 构建文档块查询（从所有知识库中检索）
            var queryBuilder = _db.DocumentChunks
                .Include(dc => dc.Document)
                .ThenInclude(d => d.KnowledgeBase);

            // 获取所有候选文档块
            var candidateChunks = await queryBuilder
                .Select(dc => new
                {
                    dc.Id,
                    dc.ChunkIndex,
                    dc.DocumentChunkContent,
                    dc.TokenCount,
                    DocumentTitle = dc.Document.DocumentTitle,
                    KnowledgeBaseName = dc.Document.KnowledgeBase.KnowledgeBaseName
                })
                .ToListAsync();

            if (!candidateChunks.Any())
            {
                Console.WriteLine("没有找到任何文档块");
                return ApiResult.Success("未找到相关文档块", new List<object>());
            }

            Console.WriteLine($"找到 {candidateChunks.Count} 个候选文档块，开始生成查询向量...");

            // 生成查询向量
            var queryVector = await _vectorService.GenerateEmbeddingAsync(query);
            if (queryVector == null || queryVector.Length == 0)
            {
                Console.WriteLine("查询向量生成失败，无法进行向量搜索");
                return ApiResult.Success("向量生成失败，无法检索相关文档", new List<object>());
            }

            Console.WriteLine("查询向量生成成功，开始获取文档块向量...");

            // 获取所有候选向量的向量数据
            var vectorData = new List<VectorData>();
            foreach (var chunk in candidateChunks)
            {
                var embedding = await _vectorService.GetVectorAsync(chunk.Id);
                if (embedding != null && embedding.Length > 0)
                {
                    vectorData.Add(new VectorData
                    {
                        ChunkId = chunk.Id,
                        Vector = embedding,
                        Content = chunk.DocumentChunkContent
                    });
                }
            }

            if (!vectorData.Any())
            {
                Console.WriteLine("没有找到有效的向量数据，无法进行相似度搜索");
                return ApiResult.Success("向量数据缺失，无法检索相关文档", new List<object>());
            }

            Console.WriteLine($"获取到 {vectorData.Count} 个有效向量，开始执行相似度搜索...");

            // 执行向量相似度搜索
            var searchResults = await _vectorService.SearchSimilarVectorsAsync(queryVector, vectorData, topK);

            if (!searchResults.Any())
            {
                Console.WriteLine("向量相似度搜索未返回任何结果，可能相似度阈值过高");
                return ApiResult.Success("未找到相似度足够高的相关文档", new List<object>());
            }

            // 设置相似度阈值，过滤掉相似度过低的结果
            var similarityThreshold = 0.5; // 相似度阈值：0.5 (50%)
            var filteredResults = searchResults.Where(r => r.Similarity >= similarityThreshold).ToList();
            
            if (!filteredResults.Any())
            {
                Console.WriteLine($"所有搜索结果相似度都低于阈值 {similarityThreshold}，最高相似度: {searchResults.Max(r => r.Similarity):F4}");
                Console.WriteLine("将切换到AI直接回答模式");
                return ApiResult.Success("未找到相似度足够高的相关文档", new List<object>());
            }

            Console.WriteLine($"相似度过滤后，保留 {filteredResults.Count} 个相关文档块（阈值: {similarityThreshold}）");

            // 构建返回结果
            var relevantChunks = filteredResults.Select(result => new
            {
                Id = result.ChunkId,
                ChunkIndex = candidateChunks.First(c => c.Id == result.ChunkId).ChunkIndex,
                DocumentChunkContent = result.Content,
                TokenCount = candidateChunks.First(c => c.Id == result.ChunkId).TokenCount,
                DocumentTitle = candidateChunks.First(c => c.Id == result.ChunkId).DocumentTitle,
                KnowledgeBaseName = candidateChunks.First(c => c.Id == result.ChunkId).KnowledgeBaseName,
                Similarity = result.Similarity
            }).ToList();

            Console.WriteLine($"从所有知识库中找到 {relevantChunks.Count} 个相关文档块，最高相似度: {filteredResults.Max(r => r.Similarity):F4}");
            return ApiResult.Success("检索完成", relevantChunks);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"检索文档块时发生异常: {ex.Message}");
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"检索文档块失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 生成答案
    /// </summary>
    public async Task<ApiResult> GenerateAnswerAsync(GenerateAnswerDto dto)
    {
        try
        {
            // 若未提供 SessionId，则自动创建一个新的会话并关闭旧的活跃会话
            if (!dto.SessionId.HasValue)
            {
                var activeSessions = await _db.Sessions
                    .Where(s => s.UserId == dto.UserId && s.SessionStatus == "active")
                    .ToListAsync();

                if (activeSessions.Count > 0)
                {
                    var now = DateTime.UtcNow;
                    foreach (var s in activeSessions)
                    {
                        s.SessionStatus = "closed";
                        s.UpdatedAt = now;
                    }
                }

                string titleBase = dto.Question?.Trim() ?? "新会话";
                string title = titleBase.Length <= 30 ? titleBase : titleBase.Substring(0, 30);

                var newSession = new Session
                {
                    Id = Guid.NewGuid(),
                    UserId = dto.UserId,
                    SessionTitle = string.IsNullOrWhiteSpace(title) ? "新会话" : title,
                    SessionStatus = "active",
                    LastActiveAt = DateTime.UtcNow,
                    CreatedAt = DateTime.UtcNow,
                    UpdatedAt = DateTime.UtcNow
                };

                _db.Sessions.Add(newSession);
                await _db.SaveChangesAsync();
                dto.SessionId = newSession.Id;
            }

            // 只有 model=="x1" 时才校验 XunfeiVersion 和 XunfeiMode
            if ((dto.Model?.ToLower() == "x1") && (string.IsNullOrWhiteSpace(dto.XunfeiVersion) || string.IsNullOrWhiteSpace(dto.XunfeiMode)))
            {
                return ApiResult.Failed(400, "XunfeiVersion 和 XunfeiMode 字段在 model 为 x1 时必填");
            }

            List<object> chunks = new List<object>();
            string context = "";
            bool useKnowledgeBase = false;

            // 自动从所有知识库中检索相关文档
            Console.WriteLine("=== 开始智能问答流程 ===");
            Console.WriteLine($"用户问题: {dto.Question}");
            Console.WriteLine("开始从所有知识库中检索相关文档...");
            
            var retrievalResult = await RetrieveRelevantChunksFromAllKnowledgeBasesAsync(dto.Question, dto.UserId, 5);
            
            if (retrievalResult.Code == 200)
            {
                chunks = JsonSerializer.Deserialize<List<object>>(JsonSerializer.Serialize(retrievalResult.Data));
                if (chunks.Count > 0)
                {
                    // 知识库中有相关文档，使用RAG模式
                    context = BuildContextFromChunks(chunks);
                    useKnowledgeBase = true;
                    Console.WriteLine($"✅ 使用知识库RAG模式，找到 {chunks.Count} 个相关文档块");
                    Console.WriteLine($"📚 构建的上下文长度: {context.Length} 字符");
                    
                    // 显示前几个文档块的标题，便于调试
                    var chunkTitles = chunks.Take(3).Select(c => {
                        var chunkObj = JsonSerializer.Deserialize<JsonElement>(JsonSerializer.Serialize(c));
                        if (chunkObj.TryGetProperty("DocumentTitle", out var title))
                            return title.GetString();
                        return "未知标题";
                    }).ToList();
                    Console.WriteLine($"📄 相关文档标题: {string.Join(", ", chunkTitles)}");
                }
                else
                {
                    Console.WriteLine("⚠️  所有知识库中都没有找到相关文档，自动切换到AI模型直接回答模式");
                    Console.WriteLine("💡 系统将使用AI模型的通用知识来回答用户问题");
                    Console.WriteLine("🔍 可能原因：1) 知识库为空 2) 相似度过低 3) 查询与知识库内容不匹配");
                }
            }
            else
            {
                Console.WriteLine($"❌ 知识库检索失败: {retrievalResult.Message}，自动切换到AI模型直接回答模式");
                Console.WriteLine("💡 系统将使用AI模型的通用知识来回答用户问题");
            }

            // 如果没有找到相关文档，直接使用AI模型
            if (!useKnowledgeBase)
            {
                Console.WriteLine("🔄 切换到AI直接回答模式");
                context = ""; // 不使用知识库上下文
                Console.WriteLine("📝 提示词模式: 直接AI回答（无知识库上下文）");
            }
            else
            {
                Console.WriteLine("📝 提示词模式: RAG增强回答（基于知识库上下文）");
            }
            
            Console.WriteLine("🤖 开始调用AI模型生成答案...");
            
            // 生成答案
            var answer = await GenerateAnswerWithAI(dto.Question, context, dto.Model, dto.MaxTokens, dto.Temperature, dto.XunfeiVersion, dto.XunfeiMode, dto.DeepseekMode);
            
            Console.WriteLine($"✅ AI答案生成完成，答案长度: {answer.Length} 字符");
            Console.WriteLine($"🎯 最终模式: {(useKnowledgeBase ? "RAG模式" : "AI直接回答模式")}");
            Console.WriteLine("=== 智能问答流程结束 ===");

            // 保存对话记录（无论是否有SessionId都保存，便于单轮和多轮都能追溯）
            var conversation = new Conversation
            {
                Id = Guid.NewGuid(),
                SessionId = dto.SessionId, // Guid? 可为null
                UserId = dto.UserId,
                ConversationQuestion = dto.Question,
                ConversationAnswer = answer,
                SourceChunks = JsonSerializer.Serialize(chunks),
                ConversationModel = dto.Model,
                PromptTokens = dto.Question.Length / 4, // 简单估算
                CompletionTokens = answer.Length / 4,
                LatencyMs = 1000, // 模拟延迟
                CreatedAt = DateTime.UtcNow,
                UpdatedAt = DateTime.UtcNow
            };
            _db.Conversations.Add(conversation);
            await _db.SaveChangesAsync();

            var result = new
            {
                Answer = answer,
                SourceChunks = chunks,
                Model = dto.Model,
                TokensUsed = dto.Question.Length / 4 + answer.Length / 4,
                SessionId = dto.SessionId,
                UseKnowledgeBase = useKnowledgeBase,
                Mode = useKnowledgeBase ? "RAG模式" : "AI直接回答模式",
                ModeDescription = useKnowledgeBase 
                    ? $"RAG模式：基于 {chunks.Count} 个相关文档块生成答案" 
                    : "AI直接回答模式：未找到相关文档，使用AI模型通用知识回答",
                SimilarityInfo = useKnowledgeBase && chunks.Count > 0
                    ? $"最高相似度: {chunks.Max(c => {
                        var chunkObj = JsonSerializer.Deserialize<JsonElement>(JsonSerializer.Serialize(c));
                        if (chunkObj.TryGetProperty("Similarity", out var sim))
                            return sim.GetDouble();
                        return 0.0;
                    }):F4}"
                    : "无相似度信息"
            };

            return ApiResult.Success(useKnowledgeBase ? "基于知识库的答案生成成功" : "AI直接回答成功", result);
        }
        catch (Exception ex)
        {
            var innerMsg = ex.InnerException?.Message;
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"生成答案失败: {ex.Message} {innerMsg}");
        }
    }





    /// <summary>
    /// 创建会话
    /// </summary>
    public async Task<ApiResult> CreateSessionAsync(CreateSessionDto dto)
    {
        try
        {
            // 关闭该用户之前的活跃会话，确保仅一个活跃会话
            var existingActiveSessions = await _db.Sessions
                .Where(s => s.UserId == dto.UserId && s.SessionStatus == "active")
                .ToListAsync();

            if (existingActiveSessions.Count > 0)
            {
                var now = DateTime.UtcNow;
                foreach (var s in existingActiveSessions)
                {
                    s.SessionStatus = "closed";
                    s.UpdatedAt = now;
                }
            }

            var session = new Session
            {
                Id = Guid.NewGuid(),
                UserId = dto.UserId,
                SessionTitle = dto.SessionTitle,
                SessionStatus = "active",
                LastActiveAt = DateTime.UtcNow,
                Metadata = dto.Metadata,
                CreatedAt = DateTime.UtcNow,
                UpdatedAt = DateTime.UtcNow
            };

            _db.Sessions.Add(session);
            await _db.SaveChangesAsync();

            return ApiResult.Success("会话创建成功", new { sessionId = session.Id });
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"创建会话失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 获取会话列表
    /// </summary>
    public async Task<ApiResult> GetSessionsAsync(Guid userId)
    {
        try
        {
            // 检查用户是否具有查看所有会话的权限
            var canViewAll = await _permissionCheckService.CanViewAllAsync(userId, "qa");
            
            var query = _db.Sessions
                .Include(s => s.User) // 包含用户信息以便显示创建者
                .AsQueryable();

            // 如果具有查看所有会话的权限，可以看到所有会话；否则只能看到自己的
            if (!canViewAll)
            {
                query = query.Where(s => s.UserId == userId);
            }

            var sessions = await query
                .OrderBy(s => s.SessionTitle).ThenBy(s => s.Id) // 使用稳定的排序方式，避免启用禁用后上下跳动
                .Select(s => new
                {
                    s.Id,
                    s.SessionTitle,
                    s.SessionStatus,
                    s.LastActiveAt,
                    s.CreatedAt,
                    CreatorName = s.User.Username, // 显示创建者用户名
                    IsOwner = s.UserId == userId, // 标识是否是当前用户的会话
                    ConversationCount = s.Conversations.Count
                })
                .ToListAsync();

            return ApiResult.Success("获取会话列表成功", sessions);
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"获取会话列表失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 获取会话详情
    /// </summary>
    public async Task<ApiResult> GetSessionAsync(Guid sessionId)
    {
        try
        {
            var session = await _db.Sessions
                .Include(s => s.Conversations)
                .FirstOrDefaultAsync(s => s.Id == sessionId);

            if (session == null)
            {
                return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "会话不存在");
            }

            var result = new
            {
                session.Id,
                session.SessionTitle,
                session.SessionStatus,
                session.LastActiveAt,
                session.CreatedAt,
                ConversationCount = session.Conversations.Count,
                Conversations = session.Conversations
                    .OrderBy(c => c.Id) // 使用稳定的排序方式，避免启用禁用后上下跳动
                    .Select(c => new
                    {
                        c.Id,
                        c.ConversationQuestion,
                        c.ConversationAnswer,
                        c.ConversationModel,
                        c.CreatedAt
                    })
                    .ToList()
            };

            return ApiResult.Success("获取会话详情成功", result);
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"获取会话详情失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 更新会话
    /// </summary>
    public async Task<ApiResult> UpdateSessionAsync(UpdateSessionDto dto)
    {
        try
        {
            // 按需求：此接口不做权限控制，仅校验会话是否存在
            var session = await _db.Sessions.FirstOrDefaultAsync(s => s.Id == dto.SessionId);
            if (session == null)
            {
                return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "会话不存在");
            }

            if (!string.IsNullOrWhiteSpace(dto.SessionTitle))
            {
                session.SessionTitle = dto.SessionTitle!.Trim();
            }

            if (!string.IsNullOrWhiteSpace(dto.SessionStatus))
            {
                session.SessionStatus = dto.SessionStatus!.Trim();
            }

            if (dto.Metadata != null)
            {
                session.Metadata = dto.Metadata;
            }

            session.UpdatedAt = DateTime.UtcNow;
            await _db.SaveChangesAsync();

            return ApiResult.Success("会话更新成功", new { sessionId = session.Id });
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"更新会话失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 删除会话
    /// </summary>
    public async Task<ApiResult> DeleteSessionAsync(Guid sessionId, Guid userId)
    {
        try
        {
            // 查找会话
            var session = await _db.Sessions
                .Include(s => s.Conversations)
                .FirstOrDefaultAsync(s => s.Id == sessionId);

            if (session == null)
            {
                return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "会话不存在");
            }

            // 检查权限：用户只能删除自己的会话
            if (session.UserId != userId)
            {
                return ApiResult.Failed((int)ApiStatusCode.FORBIDDEN, "无权限删除此会话");
            }

            // 删除会话及其相关的对话记录
            _db.Conversations.RemoveRange(session.Conversations);
            _db.Sessions.Remove(session);
            await _db.SaveChangesAsync();

            return ApiResult.Success("会话删除成功");
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"删除会话失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 发送消息
    /// </summary>
    public async Task<ApiResult> SendMessageAsync(SendMessageDto dto)
    {
        try
        {
            // 验证会话是否存在
            var session = await _db.Sessions
                .FirstOrDefaultAsync(s => s.Id == dto.SessionId && s.UserId == dto.UserId);

            if (session == null)
            {
                return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "会话不存在");
            }

            // 若会话已关闭，重新激活；并更新最后活跃时间
            session.SessionStatus = "active";
            session.LastActiveAt = DateTime.UtcNow;
            session.UpdatedAt = DateTime.UtcNow;

            // 生成答案
            var generateAnswerDto = new GenerateAnswerDto
            {
                UserId = dto.UserId,
                Question = dto.Message,
                KnowledgeBaseId = dto.KnowledgeBaseId,
                SessionId = dto.SessionId,
                Model = dto.Model,
                MaxTokens = dto.MaxTokens,
                Temperature = dto.Temperature,
                XunfeiVersion = dto.XunfeiVersion,
                XunfeiMode = dto.XunfeiMode,
                DeepseekMode = dto.DeepseekMode
            };

            var answerResult = await GenerateAnswerAsync(generateAnswerDto);
            if (answerResult.Code != 200)
            {
                return answerResult;
            }

            await _db.SaveChangesAsync();

            return answerResult;
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"发送消息失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 获取会话消息历史
    /// </summary>
    public async Task<ApiResult> GetSessionMessagesAsync(Guid sessionId)
    {
        try
        {
            var conversations = await _db.Conversations
                .Include(c => c.Session)
                .Where(c => c.SessionId == sessionId)
                .OrderBy(c => c.Id) // 使用稳定的排序方式，避免启用禁用后上下跳动
                .Select(c => new
                {
                    c.Id,
                    SessionId = c.SessionId,
                    SessionTitle = c.Session != null ? c.Session.SessionTitle : null,
                    SessionStatus = c.Session != null ? c.Session.SessionStatus : null,
                    c.ConversationQuestion,
                    c.ConversationAnswer,
                    c.ConversationModel,
                    c.PromptTokens,
                    c.CompletionTokens,
                    c.LatencyMs,
                    c.CreatedAt
                })
                .ToListAsync();

            return ApiResult.Success("获取消息历史成功", conversations);
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"获取消息历史失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 获取问答列表
    /// </summary>
    /// <summary>
    /// 调试方法：检查数据库状态
    /// </summary>
    public async Task<ApiResult> DebugDatabaseStatusAsync()
    {
        try
        {
            var totalUsers = await _db.Users.CountAsync();
            var totalConversations = await _db.Conversations.CountAsync();
            var totalSessions = await _db.Sessions.CountAsync();
            var totalDocuments = await _db.Documents.CountAsync();
            
            var recentConversations = await _db.Conversations
                .Include(c => c.User)
                .OrderByDescending(c => c.CreatedAt)
                .Take(5)
                .Select(c => new
                {
                    c.Id,
                    c.UserId,
                    UserName = c.User.Username,
                    c.ConversationQuestion,
                    c.CreatedAt
                })
                .ToListAsync();

            var result = new
            {
                TotalUsers = totalUsers,
                TotalConversations = totalConversations,
                TotalSessions = totalSessions,
                TotalDocuments = totalDocuments,
                RecentConversations = recentConversations
            };

            return ApiResult.Success("数据库状态检查", result);
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"数据库状态检查失败: {ex.Message}");
        }
    }

    public async Task<ApiResult> GetQAListAsync(Guid userId, int page = 1, int pageSize = 10)
    {
        try
        {
            // 检查用户是否具有查看所有问答记录的权限
            var canViewAll = await _permissionCheckService.CanViewAllAsync(userId, "qa");
            
            Console.WriteLine($"用户 {userId} 检查 qa.view.all 权限结果: {canViewAll}");
            
            var query = _db.Conversations
                .Include(c => c.Session)
                .Include(c => c.User) // 包含用户信息以便显示创建者
                .AsQueryable();

            // 如果具有查看所有问答记录的权限，可以看到所有记录；否则只能看到自己的
            if (!canViewAll)
            {
                query = query.Where(c => c.UserId == userId);
                Console.WriteLine($"用户 {userId} 只能查看自己的问答记录");
            }
            else
            {
                Console.WriteLine($"用户 {userId} 可以查看所有问答记录");
            }

            var totalCount = await query.CountAsync();
            Console.WriteLine($"查询到的总记录数: {totalCount}");

            var qaList = await query
                .OrderByDescending(c => c.CreatedAt)
                .ThenBy(c => c.Id) // 使用稳定的排序方式
                .Skip((page - 1) * pageSize)
                .Take(pageSize)
                .Select(c => new
                {
                    c.Id,
                    c.SessionId,
                    SessionTitle = c.Session != null ? c.Session.SessionTitle : null,
                    SessionStatus = c.Session != null ? c.Session.SessionStatus : null,
                    c.ConversationQuestion,
                    c.ConversationAnswer,
                    c.ConversationModel,
                    c.PromptTokens,
                    c.CompletionTokens,
                    c.LatencyMs,
                    c.CreatedAt,
                    CreatorName = c.User.Username, // 显示创建者用户名
                    IsOwner = c.UserId == userId // 标识是否是当前用户的问答记录
                })
                .ToListAsync();

            Console.WriteLine($"返回的问答记录数: {qaList.Count}");

            var result = new
            {
                QAList = qaList,
                TotalCount = totalCount,
                Page = page,
                PageSize = pageSize,
                TotalPages = (int)Math.Ceiling((double)totalCount / pageSize)
            };

            return ApiResult.Success("获取问答列表成功", result);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"获取问答列表异常: {ex.Message}");
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"获取问答列表失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 获取用户对话记录
    /// </summary>
    public async Task<ApiResult> GetUserConversationsAsync(GetUserConversationsDto dto)
    {
        try
        {
            // 检查用户是否具有查看所有对话记录的权限
            var canViewAll = await _permissionCheckService.CanViewAllAsync(dto.UserId, "qa");
            
            var query = _db.Conversations
                .Include(c => c.Session)
                .Include(c => c.User) // 包含用户信息以便显示创建者
                .AsQueryable();

            // 如果具有查看所有对话记录的权限，可以看到所有记录；否则只能看到自己的
            if (!canViewAll)
            {
                query = query.Where(c => c.UserId == dto.UserId);
            }

            // 时间范围过滤
            if (dto.StartDate.HasValue)
            {
                query = query.Where(c => c.CreatedAt >= dto.StartDate.Value);
            }

            if (dto.EndDate.HasValue)
            {
                query = query.Where(c => c.CreatedAt <= dto.EndDate.Value);
            }

            // 模型过滤
            if (!string.IsNullOrEmpty(dto.Model))
            {
                query = query.Where(c => c.ConversationModel == dto.Model);
            }

            var totalCount = await query.CountAsync();

            var conversations = await query
                .OrderBy(c => c.Id) // 使用稳定的排序方式，避免启用禁用后上下跳动
                .Skip((dto.Page - 1) * dto.PageSize)
                .Take(dto.PageSize)
                .Select(c => new
                {
                    c.Id,
                    c.SessionId,
                    SessionTitle = c.Session != null ? c.Session.SessionTitle : null,
                    SessionStatus = c.Session != null ? c.Session.SessionStatus : null,
                    c.ConversationQuestion,
                    c.ConversationAnswer,
                    c.ConversationModel,
                    c.PromptTokens,
                    c.CompletionTokens,
                    c.LatencyMs,
                    c.CreatedAt,
                    CreatorName = c.User.Username, // 显示创建者用户名
                    IsOwner = c.UserId == dto.UserId // 标识是否是当前用户的对话记录
                })
                .ToListAsync();

            var result = new
            {
                Conversations = conversations,
                TotalCount = totalCount,
                Page = dto.Page,
                PageSize = dto.PageSize,
                TotalPages = (int)Math.Ceiling((double)totalCount / dto.PageSize)
            };

            return ApiResult.Success("获取用户对话记录成功", result);
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"获取用户对话记录失败: {ex.Message}");
        }
    }

    #region 私有方法

    /// <summary>
    /// 将文档分割成块
    /// </summary>
    private List<string> SplitDocumentIntoChunks(string content, int chunkSize)
    {
        var chunks = new List<string>();
        var sentences = content.Split(new[] { '.', '!', '?' }, StringSplitOptions.RemoveEmptyEntries);
        
        var currentChunk = new StringBuilder();
        
        foreach (var sentence in sentences)
        {
            var trimmedSentence = sentence.Trim();
            if (string.IsNullOrEmpty(trimmedSentence)) continue;

            if (currentChunk.Length + trimmedSentence.Length > chunkSize && currentChunk.Length > 0)
            {
                chunks.Add(currentChunk.ToString().Trim());
                currentChunk.Clear();
            }

            currentChunk.Append(trimmedSentence).Append(". ");
        }

        if (currentChunk.Length > 0)
        {
            chunks.Add(currentChunk.ToString().Trim());
        }

        return chunks;
    }

    /// <summary>
    /// 从文档块构建上下文
    /// </summary>
    private string BuildContextFromChunks(List<object> chunks)
    {
        var contextBuilder = new StringBuilder();
        contextBuilder.AppendLine("基于以下文档内容回答问题：");
        contextBuilder.AppendLine();

        foreach (var chunk in chunks)
        {
            var chunkObj = JsonSerializer.Deserialize<JsonElement>(JsonSerializer.Serialize(chunk));
            
            // 显示文档标题和相似度
            if (chunkObj.TryGetProperty("DocumentTitle", out var title))
            {
                contextBuilder.AppendLine($"【文档标题: {title.GetString()}】");
            }
            
            if (chunkObj.TryGetProperty("Similarity", out var similarity))
            {
                contextBuilder.AppendLine($"【相似度: {similarity.GetDouble():F4}】");
            }
            
            contextBuilder.AppendLine();
            
            // 显示文档内容
            if (chunkObj.TryGetProperty("DocumentChunkContent", out var content))
            {
                contextBuilder.AppendLine(content.GetString());
                contextBuilder.AppendLine();
            }
            
            contextBuilder.AppendLine("---");
            contextBuilder.AppendLine();
        }

        return contextBuilder.ToString();
    }



    // 讯飞星火X1 HTTP API配置（OpenAI兼容风格）
    private static readonly string XunfeiApiPassword = "cbqtvDYsUqKBkZJSfbEL:CBHQVqszndhZFOHnAywp"; // 你的APIPassword，务必用控制台HTTP服务接口认证信息
    private static readonly string XunfeiHostUrl = "https://spark-api-open.xf-yun.com/v2/chat/completions";

    /// <summary>
    /// 调用讯飞星火X1 HTTP API（OpenAI兼容风格），返回AI答案
    /// </summary>
    private async Task<string> CallXunfeiSparkAsync(string userId, string content, string? version = null, string? mode = null)
    {
        // 打印APIPassword原文和ASCII码，便于排查
        Console.WriteLine("APIPassword原文: [" + XunfeiApiPassword + "]");
        Console.Write("APIPassword ASCII: ");
        foreach (var c in XunfeiApiPassword)
        {
            Console.Write(((int)c) + " ");
        }
        Console.WriteLine();

        // 检查APIPassword是否全为ASCII
        if (string.IsNullOrWhiteSpace(XunfeiApiPassword) || XunfeiApiPassword.Any(c => c < 32 || c > 126))
        {
            return "[AI接口调用失败]：APIPassword包含非ASCII字符或为空，请重新从讯飞控制台复制HTTP服务接口认证信息。";
        }

        string apiUrl = version == "v1"
            ? "https://spark-api.xf-yun.com/v1/chat/completions"
            : "https://spark-api-open.xf-yun.com/v2/chat/completions";
        string model = "x1"; // 讯飞API只支持x1
        var requestBody = new
        {
            model = model,
            user = userId,
            messages = new[]
            {
                new { role = "user", content = content }
            },
            stream = false
        };

        string json = System.Text.Json.JsonSerializer.Serialize(requestBody);

        using (var client = new System.Net.Http.HttpClient())
        {
            client.DefaultRequestHeaders.Clear();
            client.DefaultRequestHeaders.Add("Authorization", $"Bearer {XunfeiApiPassword}");
            var contentObj = new System.Net.Http.StringContent(json, System.Text.Encoding.UTF8, "application/json");
            try
            {
                var response = await client.PostAsync(apiUrl, contentObj);
                var result = await response.Content.ReadAsStringAsync();
                Console.WriteLine("讯飞API返回：" + result);

                // 解析讯飞返回的结果，提取AI回答内容
                using var doc = System.Text.Json.JsonDocument.Parse(result);
                var root = doc.RootElement;
                if (root.TryGetProperty("choices", out var choices) && choices.GetArrayLength() > 0)
                {
                    var message = choices[0].GetProperty("message");
                    var contentStr = message.GetProperty("content").GetString();
                    // 如果用户请求 reasoner，提示仅 deepseek 支持
                    if (mode == "reasoner")
                    {
                        return "[提示] 讯飞星火暂不支持深度推理(reasoner)模式，已自动切换为普通对话模式。\n" + (contentStr ?? "[AI无返回内容]");
                    }
                    return contentStr ?? "[AI无返回内容]";
                }
                // 也可能有错误信息
                if (root.TryGetProperty("error", out var error))
                {
                    var msg = error.TryGetProperty("message", out var msgProp) ? msgProp.GetString() : "";
                    return $"[AI接口错误] msg={msg}";
                }
            }
            catch (Exception ex)
            {
                return $"[AI接口调用失败]：{ex.Message}";
            }
            return "[AI接口调用失败]";
        }
    }

    // DeepSeek API配置
    private static readonly string DeepSeekApiKey = "sk-882e683548684568a7bdd778ec40c9a7"; // 请替换为你的真实 DeepSeek API Key
    private static readonly string DeepSeekHostUrl = "https://api.deepseek.com/v1/chat/completions";

    /// <summary>
    /// 调用DeepSeek大模型API，返回AI答案
    /// </summary>
    private async Task<string> CallDeepSeekAsync(string userId, string content, string model = "deepseek-chat")
    {
        // deepseek-chat -> DeepSeek-V3-0324
        // deepseek-reasoner -> DeepSeek-R1-0528
        string modelName = model;
        var requestBody = new
        {
            model = modelName,
            user = userId,
            messages = new[]
            {
                new { role = "user", content = content }
            },
            stream = false
        };

        string json = System.Text.Json.JsonSerializer.Serialize(requestBody);

        using (var client = new System.Net.Http.HttpClient())
        {
            client.DefaultRequestHeaders.Clear();
            client.DefaultRequestHeaders.Add("Authorization", $"Bearer {DeepSeekApiKey}");
            var contentObj = new System.Net.Http.StringContent(json, System.Text.Encoding.UTF8, "application/json");
            try
            {
                var response = await client.PostAsync(DeepSeekHostUrl, contentObj);
                var result = await response.Content.ReadAsStringAsync();
                Console.WriteLine("DeepSeek API返回：" + result);

                // 解析返回
                using var doc = System.Text.Json.JsonDocument.Parse(result);
                var root = doc.RootElement;
                if (root.TryGetProperty("choices", out var choices) && choices.GetArrayLength() > 0)
                {
                    var message = choices[0].GetProperty("message");
                    var contentStr = message.GetProperty("content").GetString();
                    return contentStr ?? "[AI无返回内容]";
                }
                if (root.TryGetProperty("error", out var error))
                {
                    var msg = error.TryGetProperty("message", out var msgProp) ? msgProp.GetString() : "";
                    return $"[AI接口错误] msg={msg}";
                }
            }
            catch (Exception ex)
            {
                return $"[AI接口调用失败]：{ex.Message}";
            }
            return "[AI接口调用失败]";
        }
    }

    /// <summary>
    /// 使用AI生成答案（智能模式）
    /// </summary>
    private async Task<string> GenerateAnswerWithAI(string question, string context, string model, int maxTokens, double temperature, string? xunfeiVersion = null, string? xunfeiMode = null, string? deepseekMode = null)
    {
        string prompt;
        
        // 根据是否有上下文构建不同的prompt
        if (!string.IsNullOrEmpty(context))
        {
            // RAG模式：基于知识库内容回答
            Console.WriteLine("🔍 构建RAG模式提示词（基于知识库上下文）");
            prompt = $@"基于以下参考资料回答用户问题：

参考资料：
{context}

问题：{question}

请基于上述参考资料专业、准确地回答用户问题。如果参考资料中没有相关信息，请明确说明。";
            Console.WriteLine($"📝 RAG提示词长度: {prompt.Length} 字符");
        }
        else
        {
            // 直接回答模式：AI模型直接回答
            Console.WriteLine("🔍 构建直接回答模式提示词（无知识库上下文）");
            prompt = $@"请回答以下问题：

问题：{question}

请提供专业、准确、有帮助的回答。";
            Console.WriteLine($"📝 直接回答提示词长度: {prompt.Length} 字符");
        }

        Console.WriteLine($"🤖 选择AI模型: {model}");
        
        // 根据模型类型调用相应的AI服务
        if (!string.IsNullOrEmpty(model) && model.ToLower().Contains("deepseek"))
        {
            var deepseekModel = deepseekMode == "reasoner" ? "deepseek-reasoner" : "deepseek-chat";
            Console.WriteLine($"🚀 调用DeepSeek API，模型: {deepseekModel}");
            return await CallDeepSeekAsync("user_id", prompt, deepseekModel);
        }
        else
        {
            Console.WriteLine($"🚀 调用讯飞星火API，版本: {xunfeiVersion}, 模式: {xunfeiMode}");
            return await CallXunfeiSparkAsync("user_id", prompt, xunfeiVersion, xunfeiMode);
        }
    }

    #endregion
}
